package sqlTestes.tComplexoSelect;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

import sql.ddl.Tabela;
import sql.ddl.coluna.Coluna;
import sql.dml.selecao.FabricaSelecao;
import sql.dml.selecao.Select;
import sql.dml.selecao.coluna.ColunaSelecao;
import sql.dml.selecao.coluna.Oque;
import sql.dml.selecao.filtro.FiltroSQl;
import sql.dml.selecao.filtro.FiltroSQlBasico;
import sql.dml.selecao.tabela.ListaOnde;
import sql.dml.selecao.tabela.Onde;
import sql.dml.selecao.tabela.TabelaSelecao;
import sql.dml.selecao.tabela.juncao.TabelaSelecaoJoin;
import sql.dml.selecao.tabela.juncao.TabelaSelecaoNaturalJoin;
import sql.dml.selecao.tabela.juncao.TipoJuncaoPesquisa;

public class TesteSelecaoComJuncaoDeTabelas {
	Select obj;

	FiltroSQl[] filtros;

	Tabela tabela1 = new Tabela("Tabela1");

	Tabela tabela2 = new Tabela("Tabela2");

	Tabela tabela3 = new Tabela("Tabela3");

	@Before
	public void up() {
		filtros = new FiltroSQl[] { new FiltroSQlBasico("a", "b", "="),
				new FiltroSQlBasico("a", "2", "=") };
	}

	@Test
	public void tabela1NaturalInnerJoinTabela1TodasAsColunas() {
		Onde tabela = new TabelaSelecaoNaturalJoin(new TabelaSelecao(tabela1,
				null), new TabelaSelecao(tabela2, null));
		obj = FabricaSelecao.fabricaSelecao(new Onde[] { tabela });
		Assert.assertEquals("SELECT * FROM Tabela1 NATURAL INNER JOIN Tabela2",
				obj.codigoSQL());
	}

	@Test
	public void tabela1NaturalRightJoinTabela1TodasAsColunas() {
		Onde tabela = new TabelaSelecaoNaturalJoin(new TabelaSelecao(tabela1,
				null), new TabelaSelecao(tabela2, null),
				TipoJuncaoPesquisa.RIGHT);

		ListaOnde tabelas = new ListaOnde();
		tabelas.add(tabela);
		obj = FabricaSelecao.fabricaSelecao(new Onde[] { tabela });
		Assert.assertEquals("SELECT * FROM Tabela1 NATURAL RIGHT JOIN Tabela2",
				obj.codigoSQL());
	}

	@Test
	public void selecaoTabela1RightJoinTabela2ComFiltro() {
		Onde tabela = new TabelaSelecaoJoin(new TabelaSelecao(tabela1),
				new TabelaSelecao(tabela2), TipoJuncaoPesquisa.RIGHT, filtros);
		ListaOnde tabelas = new ListaOnde();
		tabelas.add(tabela);
		obj = FabricaSelecao.fabricaSelecao(new Onde[] { tabela });
		Assert.assertEquals(
				"SELECT * FROM Tabela1 RIGHT JOIN Tabela2 ON a = b AND a = 2",
				obj.codigoSQL());
	}

	@Test
	public void selecaoTabela1LeftJoinTabela2ComFiltro() {
		Onde tabela = new TabelaSelecaoJoin(new TabelaSelecao(tabela1),
				new TabelaSelecao(tabela2), TipoJuncaoPesquisa.LEFT, filtros);
		ListaOnde tabelas = new ListaOnde();
		tabelas.add(tabela);
		obj = FabricaSelecao.fabricaSelecao(new Onde[] { tabela });
		Assert.assertEquals(
				"SELECT * FROM Tabela1 LEFT JOIN Tabela2 ON a = b AND a = 2",
				obj.codigoSQL());
	}

	@Test
	public void selecaoTabela1JuncaoTabela2Tabela3JuncaoTabela2() {
		Onde tabela = new TabelaSelecaoJoin(new TabelaSelecao(tabela1),
				new TabelaSelecao(tabela2), TipoJuncaoPesquisa.LEFT, filtros);
		ListaOnde tabelas = new ListaOnde();
		tabelas.add(tabela);
		Onde tabelae = new TabelaSelecaoNaturalJoin(new TabelaSelecao(tabela3,
				null), new TabelaSelecao(tabela2, null));

		obj = FabricaSelecao.fabricaSelecao(new Onde[] { tabela, tabelae },
				new FiltroSQlBasico("a", "b", ">"));

		Assert
				.assertEquals(
						"SELECT * FROM Tabela1 LEFT JOIN Tabela2 ON a = b AND a = 2,Tabela3 NATURAL INNER JOIN Tabela2 WHERE a > b",
						obj.codigoSQL());
	}

	@Test
	public void selecaoJuncaoComAlias() {
		FiltroSQl[] filtroEsta = {
				new FiltroSQlBasico("meuAlias.a", "meuAlias2.b", "="),
				new FiltroSQlBasico("a", "2", "=") };

		Onde tabela = new TabelaSelecaoJoin(new TabelaSelecao(tabela1, null,
				"meuAlias"), new TabelaSelecao(tabela2, null, "meuAlias2"),
				TipoJuncaoPesquisa.LEFT, filtroEsta);

		Onde tabelae = new TabelaSelecaoNaturalJoin(new TabelaSelecao(tabela3,
				null), new TabelaSelecao(tabela2, null));

		obj = FabricaSelecao.fabricaSelecao(new Onde[] { tabela, tabelae },
				new FiltroSQlBasico("a", "b", ">"));

		Assert.assertEquals("SELECT * FROM Tabela1 AS meuAlias LEFT "
				+ "JOIN Tabela2 AS meuAlias2 ON meuAlias.a = meuAlias2.b "
				+ "AND a = 2,Tabela3 NATURAL INNER JOIN Tabela2 WHERE a > b",
				obj.codigoSQL());
	}

	@Test
	public void selectTabela1Tabela2ComApenasNomesDasColunas() {

		TabelaSelecao t1 = new TabelaSelecao(tabela1);
		TabelaSelecao t2 = new TabelaSelecao(tabela2);
		TabelaSelecaoNaturalJoin naturalJuncao = new TabelaSelecaoNaturalJoin(
				t1, t2);
		obj = FabricaSelecao.fabricaSelecao(new Onde[] { naturalJuncao },
				new Oque[] { new ColunaSelecao(new Coluna("int", "a")),
						new ColunaSelecao(new Coluna("int", "b")) });
		Assert.assertEquals(
				"SELECT a,b FROM Tabela1 NATURAL INNER JOIN Tabela2", obj
						.codigoSQL());
	}

	@Test
	public void selectTabela1JuncaoTabela2ComAliasEmColunas() {
		TabelaSelecao t1 = new TabelaSelecao(tabela1);
		TabelaSelecao t2 = new TabelaSelecao(tabela2);
		TabelaSelecaoNaturalJoin naturalJuncao = new TabelaSelecaoNaturalJoin(
				t1, t2);
		obj = FabricaSelecao.fabricaSelecao(new Onde[] { naturalJuncao },
				new Oque[] {
						new ColunaSelecao(new Coluna("int", "a"), t1, "a"),
						new ColunaSelecao(new Coluna("int", "b"), t2) });
		Assert
				.assertEquals(
						"SELECT Tabela1.a AS a,Tabela2.b FROM Tabela1 NATURAL INNER JOIN Tabela2",
						obj.codigoSQL());
	}

	@Test
	public void selecaoColunasDandoAliasEUsandoAliasDaJuncaoDeTabelas() {
		TabelaSelecao s1 = new TabelaSelecao(tabela1, null, "meuAlias");
		TabelaSelecao s2 = new TabelaSelecao(tabela2, null, "meuAlias2");

		TabelaSelecaoJoin st = new TabelaSelecaoJoin(s1, s2,
				TipoJuncaoPesquisa.LEFT, new FiltroSQlBasico("meuAlias.a",
						"meuAlias2.b", "="), new FiltroSQlBasico("a", "2", "="));

		TabelaSelecao s2_2 = new TabelaSelecao(new Tabela("Tabela2"));
		TabelaSelecao s3 = new TabelaSelecao(new Tabela("Tabela3"));

		TabelaSelecaoNaturalJoin st2 = new TabelaSelecaoNaturalJoin(s3, s2_2,
				TipoJuncaoPesquisa.INNER);

		obj = FabricaSelecao.fabricaSelecao(new Onde[] { st, st2 }, new Oque[] {
				new ColunaSelecao(new Coluna("int", "a"), s1, "perneta"),
				new ColunaSelecao(new Coluna("int", "b"), s2) },
				new FiltroSQlBasico("a", "b", ">"));

		Assert.assertEquals("SELECT meuAlias.a AS perneta,meuAlias2.b "
				+ "FROM Tabela1 AS meuAlias LEFT JOIN Tabela2 AS meuAlias2 "
				+ "ON meuAlias.a = meuAlias2.b AND a = 2,Tabela3 "
				+ "NATURAL INNER JOIN Tabela2 WHERE a > b", obj.codigoSQL());
	}
}
